home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / compiler / pyassem.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-29  |  28KB  |  940 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''A flow graph representation for Python bytecode'''
  5. import dis
  6. import new
  7. import sys
  8. from compiler import misc
  9. from compiler.consts import CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS
  10.  
  11. class FlowGraph:
  12.     
  13.     def __init__(self):
  14.         self.current = self.entry = Block()
  15.         self.exit = Block('exit')
  16.         self.blocks = misc.Set()
  17.         self.blocks.add(self.entry)
  18.         self.blocks.add(self.exit)
  19.  
  20.     
  21.     def startBlock(self, block):
  22.         if self._debug:
  23.             if self.current:
  24.                 print 'end', repr(self.current)
  25.                 print '    next', self.current.next
  26.                 print '   ', self.current.get_children()
  27.             
  28.             print repr(block)
  29.         
  30.         self.current = block
  31.  
  32.     
  33.     def nextBlock(self, block = None):
  34.         if block is None:
  35.             block = self.newBlock()
  36.         
  37.         self.current.addNext(block)
  38.         self.startBlock(block)
  39.  
  40.     
  41.     def newBlock(self):
  42.         b = Block()
  43.         self.blocks.add(b)
  44.         return b
  45.  
  46.     
  47.     def startExitBlock(self):
  48.         self.startBlock(self.exit)
  49.  
  50.     _debug = 0
  51.     
  52.     def _enable_debug(self):
  53.         self._debug = 1
  54.  
  55.     
  56.     def _disable_debug(self):
  57.         self._debug = 0
  58.  
  59.     
  60.     def emit(self, *inst):
  61.         if self._debug:
  62.             print '\t', inst
  63.         
  64.         if inst[0] in ('RETURN_VALUE', 'YIELD_VALUE'):
  65.             self.current.addOutEdge(self.exit)
  66.         
  67.         if len(inst) == 2 and isinstance(inst[1], Block):
  68.             self.current.addOutEdge(inst[1])
  69.         
  70.         self.current.emit(inst)
  71.  
  72.     
  73.     def getBlocksInOrder(self):
  74.         '''Return the blocks in reverse postorder
  75.  
  76.         i.e. each node appears before all of its successors
  77.         '''
  78.         for b in self.blocks.elements():
  79.             if b is self.exit:
  80.                 continue
  81.             
  82.             if not b.next:
  83.                 b.addNext(self.exit)
  84.                 continue
  85.         
  86.         order = dfs_postorder(self.entry, { })
  87.         order.reverse()
  88.         self.fixupOrder(order, self.exit)
  89.         if self.exit not in order:
  90.             order.append(self.exit)
  91.         
  92.         return order
  93.  
  94.     
  95.     def fixupOrder(self, blocks, default_next):
  96.         '''Fixup bad order introduced by DFS.'''
  97.         self.fixupOrderHonorNext(blocks, default_next)
  98.         self.fixupOrderForward(blocks, default_next)
  99.  
  100.     
  101.     def fixupOrderHonorNext(self, blocks, default_next):
  102.         '''Fix one problem with DFS.
  103.  
  104.         The DFS uses child block, but doesn\'t know about the special
  105.         "next" block.  As a result, the DFS can order blocks so that a
  106.         block isn\'t next to the right block for implicit control
  107.         transfers.
  108.         '''
  109.         index = { }
  110.         for i in range(len(blocks)):
  111.             index[blocks[i]] = i
  112.         
  113.         for i in range(0, len(blocks) - 1):
  114.             b = blocks[i]
  115.             n = blocks[i + 1]
  116.             if not (b.next) and b.next[0] == default_next or b.next[0] == n:
  117.                 continue
  118.             
  119.             cur = b
  120.             chain = []
  121.             elt = cur
  122.             while elt.next and elt.next[0] != default_next:
  123.                 chain.append(elt.next[0])
  124.                 elt = elt.next[0]
  125.             l = []
  126.             for b in chain:
  127.                 if not index[b] > i:
  128.                     raise AssertionError
  129.                 l.append((index[b], b))
  130.             
  131.             l.sort()
  132.             l.reverse()
  133.             for j, b in l:
  134.                 del blocks[index[b]]
  135.             
  136.             blocks[i:i + 1] = [
  137.                 cur] + chain
  138.             for i in range(len(blocks)):
  139.                 index[blocks[i]] = i
  140.             
  141.         
  142.  
  143.     
  144.     def fixupOrderForward(self, blocks, default_next):
  145.         '''Make sure all JUMP_FORWARDs jump forward'''
  146.         index = { }
  147.         chains = []
  148.         cur = []
  149.         for b in blocks:
  150.             index[b] = len(chains)
  151.             cur.append(b)
  152.             if b.next and b.next[0] == default_next:
  153.                 chains.append(cur)
  154.                 cur = []
  155.                 continue
  156.         
  157.         chains.append(cur)
  158.         while None:
  159.             constraints = []
  160.             for i in range(len(chains)):
  161.                 l = chains[i]
  162.                 for b in l:
  163.                     for c in b.get_children():
  164.                         if index[c] < i:
  165.                             forward_p = 0
  166.                             for inst in b.insts:
  167.                                 if inst[0] == 'JUMP_FORWARD':
  168.                                     if inst[1] == c:
  169.                                         forward_p = 1
  170.                                     
  171.                                 inst[1] == c
  172.                             
  173.                             if not forward_p:
  174.                                 continue
  175.                             
  176.                             constraints.append((index[c], i))
  177.                             continue
  178.                     
  179.                 
  180.             
  181.             if not constraints:
  182.                 break
  183.             
  184.             (goes_before, a_chain) = constraints[0]
  185.             if not a_chain > goes_before:
  186.                 raise AssertionError
  187.             c = chains[a_chain]
  188.             chains.remove(c)
  189.             chains.insert(goes_before, c)
  190.             continue
  191.             del blocks[:]
  192.             for c in chains:
  193.                 for b in c:
  194.                     blocks.append(b)
  195.                 
  196.             
  197.  
  198.     
  199.     def getBlocks(self):
  200.         return self.blocks.elements()
  201.  
  202.     
  203.     def getRoot(self):
  204.         '''Return nodes appropriate for use with dominator'''
  205.         return self.entry
  206.  
  207.     
  208.     def getContainedGraphs(self):
  209.         l = []
  210.         for b in self.getBlocks():
  211.             l.extend(b.getContainedGraphs())
  212.         
  213.         return l
  214.  
  215.  
  216.  
  217. def dfs_postorder(b, seen):
  218.     '''Depth-first search of tree rooted at b, return in postorder'''
  219.     order = []
  220.     seen[b] = b
  221.     for c in b.get_children():
  222.         if seen.has_key(c):
  223.             continue
  224.         
  225.         order = order + dfs_postorder(c, seen)
  226.     
  227.     order.append(b)
  228.     return order
  229.  
  230.  
  231. class Block:
  232.     _count = 0
  233.     
  234.     def __init__(self, label = ''):
  235.         self.insts = []
  236.         self.inEdges = misc.Set()
  237.         self.outEdges = misc.Set()
  238.         self.label = label
  239.         self.bid = Block._count
  240.         self.next = []
  241.         Block._count = Block._count + 1
  242.  
  243.     
  244.     def __repr__(self):
  245.         if self.label:
  246.             return '<block %s id=%d>' % (self.label, self.bid)
  247.         else:
  248.             return '<block id=%d>' % self.bid
  249.  
  250.     
  251.     def __str__(self):
  252.         insts = map(str, self.insts)
  253.         return '<block %s %d:\n%s>' % (self.label, self.bid, '\n'.join(insts))
  254.  
  255.     
  256.     def emit(self, inst):
  257.         op = inst[0]
  258.         if op[:4] == 'JUMP':
  259.             self.outEdges.add(inst[1])
  260.         
  261.         self.insts.append(inst)
  262.  
  263.     
  264.     def getInstructions(self):
  265.         return self.insts
  266.  
  267.     
  268.     def addInEdge(self, block):
  269.         self.inEdges.add(block)
  270.  
  271.     
  272.     def addOutEdge(self, block):
  273.         self.outEdges.add(block)
  274.  
  275.     
  276.     def addNext(self, block):
  277.         self.next.append(block)
  278.         if not len(self.next) == 1:
  279.             raise AssertionError, map(str, self.next)
  280.  
  281.     _uncond_transfer = ('RETURN_VALUE', 'RAISE_VARARGS', 'YIELD_VALUE', 'JUMP_ABSOLUTE', 'JUMP_FORWARD', 'CONTINUE_LOOP')
  282.     
  283.     def pruneNext(self):
  284.         """Remove bogus edge for unconditional transfers
  285.  
  286.         Each block has a next edge that accounts for implicit control
  287.         transfers, e.g. from a JUMP_IF_FALSE to the block that will be
  288.         executed if the test is true.
  289.  
  290.         These edges must remain for the current assembler code to
  291.         work. If they are removed, the dfs_postorder gets things in
  292.         weird orders.  However, they shouldn't be there for other
  293.         purposes, e.g. conversion to SSA form.  This method will
  294.         remove the next edge when it follows an unconditional control
  295.         transfer.
  296.         """
  297.         
  298.         try:
  299.             (op, arg) = self.insts[-1]
  300.         except (IndexError, ValueError):
  301.             return None
  302.  
  303.         if op in self._uncond_transfer:
  304.             self.next = []
  305.         
  306.  
  307.     
  308.     def get_children(self):
  309.         if self.next and self.next[0] in self.outEdges:
  310.             self.outEdges.remove(self.next[0])
  311.         
  312.         return self.outEdges.elements() + self.next
  313.  
  314.     
  315.     def getContainedGraphs(self):
  316.         '''Return all graphs contained within this block.
  317.  
  318.         For example, a MAKE_FUNCTION block will contain a reference to
  319.         the graph for the function body.
  320.         '''
  321.         contained = []
  322.         for inst in self.insts:
  323.             if len(inst) == 1:
  324.                 continue
  325.             
  326.             op = inst[1]
  327.             if hasattr(op, 'graph'):
  328.                 contained.append(op.graph)
  329.                 continue
  330.         
  331.         return contained
  332.  
  333.  
  334. RAW = 'RAW'
  335. FLAT = 'FLAT'
  336. CONV = 'CONV'
  337. DONE = 'DONE'
  338.  
  339. class PyFlowGraph(FlowGraph):
  340.     super_init = FlowGraph.__init__
  341.     
  342.     def __init__(self, name, filename, args = (), optimized = 0, klass = None):
  343.         self.super_init()
  344.         self.name = name
  345.         self.filename = filename
  346.         self.docstring = None
  347.         self.args = args
  348.         self.argcount = getArgCount(args)
  349.         self.klass = klass
  350.         if optimized:
  351.             self.flags = CO_OPTIMIZED | CO_NEWLOCALS
  352.         else:
  353.             self.flags = 0
  354.         self.consts = []
  355.         self.names = []
  356.         self.freevars = []
  357.         self.cellvars = []
  358.         self.closure = []
  359.         if not list(args):
  360.             pass
  361.         self.varnames = []
  362.         for i in range(len(self.varnames)):
  363.             var = self.varnames[i]
  364.             if isinstance(var, TupleArg):
  365.                 self.varnames[i] = var.getName()
  366.                 continue
  367.         
  368.         self.stage = RAW
  369.  
  370.     
  371.     def setDocstring(self, doc):
  372.         self.docstring = doc
  373.  
  374.     
  375.     def setFlag(self, flag):
  376.         self.flags = self.flags | flag
  377.         if flag == CO_VARARGS:
  378.             self.argcount = self.argcount - 1
  379.         
  380.  
  381.     
  382.     def checkFlag(self, flag):
  383.         if self.flags & flag:
  384.             return 1
  385.         
  386.  
  387.     
  388.     def setFreeVars(self, names):
  389.         self.freevars = list(names)
  390.  
  391.     
  392.     def setCellVars(self, names):
  393.         self.cellvars = names
  394.  
  395.     
  396.     def getCode(self):
  397.         '''Get a Python code object'''
  398.         if not self.stage == RAW:
  399.             raise AssertionError
  400.         self.computeStackDepth()
  401.         self.flattenGraph()
  402.         if not self.stage == FLAT:
  403.             raise AssertionError
  404.         self.convertArgs()
  405.         if not self.stage == CONV:
  406.             raise AssertionError
  407.         self.makeByteCode()
  408.         if not self.stage == DONE:
  409.             raise AssertionError
  410.         return self.newCodeObject()
  411.  
  412.     
  413.     def dump(self, io = None):
  414.         if io:
  415.             save = sys.stdout
  416.             sys.stdout = io
  417.         
  418.         pc = 0
  419.         for t in self.insts:
  420.             opname = t[0]
  421.             if opname == 'SET_LINENO':
  422.                 print 
  423.             
  424.             if len(t) == 1:
  425.                 print '\t', '%3d' % pc, opname
  426.                 pc = pc + 1
  427.                 continue
  428.             print '\t', '%3d' % pc, opname, t[1]
  429.             pc = pc + 3
  430.         
  431.         if io:
  432.             sys.stdout = save
  433.         
  434.  
  435.     
  436.     def computeStackDepth(self):
  437.         '''Compute the max stack depth.
  438.  
  439.         Approach is to compute the stack effect of each basic block.
  440.         Then find the path through the code with the largest total
  441.         effect.
  442.         '''
  443.         depth = { }
  444.         exit = None
  445.         for b in self.getBlocks():
  446.             depth[b] = findDepth(b.getInstructions())
  447.         
  448.         seen = { }
  449.         
  450.         def max_depth(b, d):
  451.             if seen.has_key(b):
  452.                 return d
  453.             
  454.             seen[b] = 1
  455.             d = d + depth[b]
  456.             children = b.get_children()
  457.             if children:
  458.                 return []([ max_depth(c, d) for c in children ])
  459.             elif not b.label == 'exit':
  460.                 return max_depth(self.exit, d)
  461.             else:
  462.                 return d
  463.  
  464.         self.stacksize = max_depth(self.entry, 0)
  465.  
  466.     
  467.     def flattenGraph(self):
  468.         '''Arrange the blocks in order and resolve jumps'''
  469.         if not self.stage == RAW:
  470.             raise AssertionError
  471.         self.insts = insts = []
  472.         pc = 0
  473.         begin = { }
  474.         end = { }
  475.         for b in self.getBlocksInOrder():
  476.             begin[b] = pc
  477.             for inst in b.getInstructions():
  478.                 insts.append(inst)
  479.                 if len(inst) == 1:
  480.                     pc = pc + 1
  481.                     continue
  482.                 if inst[0] != 'SET_LINENO':
  483.                     pc = pc + 3
  484.                     continue
  485.             
  486.             end[b] = pc
  487.         
  488.         pc = 0
  489.         for i in range(len(insts)):
  490.             inst = insts[i]
  491.             if len(inst) == 1:
  492.                 pc = pc + 1
  493.             elif inst[0] != 'SET_LINENO':
  494.                 pc = pc + 3
  495.             
  496.             opname = inst[0]
  497.             if self.hasjrel.has_elt(opname):
  498.                 oparg = inst[1]
  499.                 offset = begin[oparg] - pc
  500.                 insts[i] = (opname, offset)
  501.                 continue
  502.             if self.hasjabs.has_elt(opname):
  503.                 insts[i] = (opname, begin[inst[1]])
  504.                 continue
  505.         
  506.         self.stage = FLAT
  507.  
  508.     hasjrel = misc.Set()
  509.     for i in dis.hasjrel:
  510.         hasjrel.add(dis.opname[i])
  511.     
  512.     hasjabs = misc.Set()
  513.     for i in dis.hasjabs:
  514.         hasjabs.add(dis.opname[i])
  515.     
  516.     
  517.     def convertArgs(self):
  518.         '''Convert arguments from symbolic to concrete form'''
  519.         if not self.stage == FLAT:
  520.             raise AssertionError
  521.         self.consts.insert(0, self.docstring)
  522.         self.sort_cellvars()
  523.         for i in range(len(self.insts)):
  524.             t = self.insts[i]
  525.             if len(t) == 2:
  526.                 (opname, oparg) = t
  527.                 conv = self._converters.get(opname, None)
  528.                 if conv:
  529.                     self.insts[i] = (opname, conv(self, oparg))
  530.                 
  531.             conv
  532.         
  533.         self.stage = CONV
  534.  
  535.     
  536.     def sort_cellvars(self):
  537.         '''Sort cellvars in the order of varnames and prune from freevars.
  538.         '''
  539.         cells = { }
  540.         for name in self.cellvars:
  541.             cells[name] = 1
  542.         
  543.         self.cellvars = _[1]
  544.         for name in self.cellvars:
  545.             del cells[name]
  546.         
  547.         self.cellvars = self.cellvars + cells.keys()
  548.         self.closure = self.cellvars + self.freevars
  549.  
  550.     
  551.     def _lookupName(self, name, list):
  552.         """Return index of name in list, appending if necessary
  553.  
  554.         This routine uses a list instead of a dictionary, because a
  555.         dictionary can't store two different keys if the keys have the
  556.         same value but different types, e.g. 2 and 2L.  The compiler
  557.         must treat these two separately, so it does an explicit type
  558.         comparison before comparing the values.
  559.         """
  560.         t = type(name)
  561.         for i in range(len(list)):
  562.             if t == type(list[i]) and list[i] == name:
  563.                 return i
  564.                 continue
  565.         
  566.         end = len(list)
  567.         list.append(name)
  568.         return end
  569.  
  570.     _converters = { }
  571.     
  572.     def _convert_LOAD_CONST(self, arg):
  573.         if hasattr(arg, 'getCode'):
  574.             arg = arg.getCode()
  575.         
  576.         return self._lookupName(arg, self.consts)
  577.  
  578.     
  579.     def _convert_LOAD_FAST(self, arg):
  580.         self._lookupName(arg, self.names)
  581.         return self._lookupName(arg, self.varnames)
  582.  
  583.     _convert_STORE_FAST = _convert_LOAD_FAST
  584.     _convert_DELETE_FAST = _convert_LOAD_FAST
  585.     
  586.     def _convert_LOAD_NAME(self, arg):
  587.         if self.klass is None:
  588.             self._lookupName(arg, self.varnames)
  589.         
  590.         return self._lookupName(arg, self.names)
  591.  
  592.     
  593.     def _convert_NAME(self, arg):
  594.         if self.klass is None:
  595.             self._lookupName(arg, self.varnames)
  596.         
  597.         return self._lookupName(arg, self.names)
  598.  
  599.     _convert_STORE_NAME = _convert_NAME
  600.     _convert_DELETE_NAME = _convert_NAME
  601.     _convert_IMPORT_NAME = _convert_NAME
  602.     _convert_IMPORT_FROM = _convert_NAME
  603.     _convert_STORE_ATTR = _convert_NAME
  604.     _convert_LOAD_ATTR = _convert_NAME
  605.     _convert_DELETE_ATTR = _convert_NAME
  606.     _convert_LOAD_GLOBAL = _convert_NAME
  607.     _convert_STORE_GLOBAL = _convert_NAME
  608.     _convert_DELETE_GLOBAL = _convert_NAME
  609.     
  610.     def _convert_DEREF(self, arg):
  611.         self._lookupName(arg, self.names)
  612.         self._lookupName(arg, self.varnames)
  613.         return self._lookupName(arg, self.closure)
  614.  
  615.     _convert_LOAD_DEREF = _convert_DEREF
  616.     _convert_STORE_DEREF = _convert_DEREF
  617.     
  618.     def _convert_LOAD_CLOSURE(self, arg):
  619.         self._lookupName(arg, self.varnames)
  620.         return self._lookupName(arg, self.closure)
  621.  
  622.     _cmp = list(dis.cmp_op)
  623.     
  624.     def _convert_COMPARE_OP(self, arg):
  625.         return self._cmp.index(arg)
  626.  
  627.     for name, obj in locals().items():
  628.         if name[:9] == '_convert_':
  629.             opname = name[9:]
  630.             _converters[opname] = obj
  631.             continue
  632.     
  633.     del name
  634.     del obj
  635.     del opname
  636.     
  637.     def makeByteCode(self):
  638.         if not self.stage == CONV:
  639.             raise AssertionError
  640.         self.lnotab = lnotab = LineAddrTable()
  641.         for t in self.insts:
  642.             opname = t[0]
  643.             if len(t) == 1:
  644.                 lnotab.addCode(self.opnum[opname])
  645.                 continue
  646.             oparg = t[1]
  647.             if opname == 'SET_LINENO':
  648.                 lnotab.nextLine(oparg)
  649.                 continue
  650.             
  651.             (hi, lo) = twobyte(oparg)
  652.             
  653.             try:
  654.                 lnotab.addCode(self.opnum[opname], lo, hi)
  655.             continue
  656.             except ValueError:
  657.                 print opname, oparg
  658.                 print self.opnum[opname], lo, hi
  659.                 raise 
  660.                 continue
  661.             
  662.  
  663.         
  664.         self.stage = DONE
  665.  
  666.     opnum = { }
  667.     for num in range(len(dis.opname)):
  668.         opnum[dis.opname[num]] = num
  669.     
  670.     del num
  671.     
  672.     def newCodeObject(self):
  673.         if not self.stage == DONE:
  674.             raise AssertionError
  675.         if self.flags & CO_NEWLOCALS == 0:
  676.             nlocals = 0
  677.         else:
  678.             nlocals = len(self.varnames)
  679.         argcount = self.argcount
  680.         if self.flags & CO_VARKEYWORDS:
  681.             argcount = argcount - 1
  682.         
  683.         return new.code(argcount, nlocals, self.stacksize, self.flags, self.lnotab.getCode(), self.getConsts(), tuple(self.names), tuple(self.varnames), self.filename, self.name, self.lnotab.firstline, self.lnotab.getTable(), tuple(self.freevars), tuple(self.cellvars))
  684.  
  685.     
  686.     def getConsts(self):
  687.         '''Return a tuple for the const slot of the code object
  688.  
  689.         Must convert references to code (MAKE_FUNCTION) to code
  690.         objects recursively.
  691.         '''
  692.         l = []
  693.         for elt in self.consts:
  694.             if isinstance(elt, PyFlowGraph):
  695.                 elt = elt.getCode()
  696.             
  697.             l.append(elt)
  698.         
  699.         return tuple(l)
  700.  
  701.  
  702.  
  703. def isJump(opname):
  704.     if opname[:4] == 'JUMP':
  705.         return 1
  706.     
  707.  
  708.  
  709. class TupleArg:
  710.     '''Helper for marking func defs with nested tuples in arglist'''
  711.     
  712.     def __init__(self, count, names):
  713.         self.count = count
  714.         self.names = names
  715.  
  716.     
  717.     def __repr__(self):
  718.         return 'TupleArg(%s, %s)' % (self.count, self.names)
  719.  
  720.     
  721.     def getName(self):
  722.         return '.%d' % self.count
  723.  
  724.  
  725.  
  726. def getArgCount(args):
  727.     argcount = len(args)
  728.     if args:
  729.         for arg in args:
  730.             if isinstance(arg, TupleArg):
  731.                 numNames = len(misc.flatten(arg.names))
  732.                 argcount = argcount - numNames
  733.                 continue
  734.         
  735.     
  736.     return argcount
  737.  
  738.  
  739. def twobyte(val):
  740.     '''Convert an int argument into high and low bytes'''
  741.     if not isinstance(val, int):
  742.         raise AssertionError
  743.     return divmod(val, 256)
  744.  
  745.  
  746. class LineAddrTable:
  747.     """lnotab
  748.  
  749.     This class builds the lnotab, which is documented in compile.c.
  750.     Here's a brief recap:
  751.  
  752.     For each SET_LINENO instruction after the first one, two bytes are
  753.     added to lnotab.  (In some cases, multiple two-byte entries are
  754.     added.)  The first byte is the distance in bytes between the
  755.     instruction for the last SET_LINENO and the current SET_LINENO.
  756.     The second byte is offset in line numbers.  If either offset is
  757.     greater than 255, multiple two-byte entries are added -- see
  758.     compile.c for the delicate details.
  759.     """
  760.     
  761.     def __init__(self):
  762.         self.code = []
  763.         self.codeOffset = 0
  764.         self.firstline = 0
  765.         self.lastline = 0
  766.         self.lastoff = 0
  767.         self.lnotab = []
  768.  
  769.     
  770.     def addCode(self, *args):
  771.         for arg in args:
  772.             self.code.append(chr(arg))
  773.         
  774.         self.codeOffset = self.codeOffset + len(args)
  775.  
  776.     
  777.     def nextLine(self, lineno):
  778.         if self.firstline == 0:
  779.             self.firstline = lineno
  780.             self.lastline = lineno
  781.         else:
  782.             addr = self.codeOffset - self.lastoff
  783.             line = lineno - self.lastline
  784.             if line >= 0:
  785.                 push = self.lnotab.append
  786.                 while addr > 255:
  787.                     push(255)
  788.                     push(0)
  789.                     addr -= 255
  790.                 while line > 255:
  791.                     push(addr)
  792.                     push(255)
  793.                     line -= 255
  794.                     addr = 0
  795.                 if addr > 0 or line > 0:
  796.                     push(addr)
  797.                     push(line)
  798.                 
  799.                 self.lastline = lineno
  800.                 self.lastoff = self.codeOffset
  801.             
  802.  
  803.     
  804.     def getCode(self):
  805.         return ''.join(self.code)
  806.  
  807.     
  808.     def getTable(self):
  809.         return ''.join(map(chr, self.lnotab))
  810.  
  811.  
  812.  
  813. class StackDepthTracker:
  814.     
  815.     def findDepth(self, insts, debug = 0):
  816.         depth = 0
  817.         maxDepth = 0
  818.         for i in insts:
  819.             opname = i[0]
  820.             if debug:
  821.                 print i,
  822.             
  823.             delta = self.effect.get(opname, None)
  824.             if delta is not None:
  825.                 depth = depth + delta
  826.             else:
  827.                 for pat, pat_delta in self.patterns:
  828.                     if opname[:len(pat)] == pat:
  829.                         delta = pat_delta
  830.                         depth = depth + delta
  831.                         break
  832.                         continue
  833.                 
  834.                 if delta is None:
  835.                     meth = getattr(self, opname, None)
  836.                     if meth is not None:
  837.                         depth = depth + meth(i[1])
  838.                     
  839.                 
  840.             if depth > maxDepth:
  841.                 maxDepth = depth
  842.             
  843.             if debug:
  844.                 print depth, maxDepth
  845.                 continue
  846.         
  847.         return maxDepth
  848.  
  849.     effect = {
  850.         'POP_TOP': -1,
  851.         'DUP_TOP': 1,
  852.         'LIST_APPEND': -2,
  853.         'SLICE+1': -1,
  854.         'SLICE+2': -1,
  855.         'SLICE+3': -2,
  856.         'STORE_SLICE+0': -1,
  857.         'STORE_SLICE+1': -2,
  858.         'STORE_SLICE+2': -2,
  859.         'STORE_SLICE+3': -3,
  860.         'DELETE_SLICE+0': -1,
  861.         'DELETE_SLICE+1': -2,
  862.         'DELETE_SLICE+2': -2,
  863.         'DELETE_SLICE+3': -3,
  864.         'STORE_SUBSCR': -3,
  865.         'DELETE_SUBSCR': -2,
  866.         'PRINT_ITEM': -1,
  867.         'RETURN_VALUE': -1,
  868.         'YIELD_VALUE': -1,
  869.         'EXEC_STMT': -3,
  870.         'BUILD_CLASS': -2,
  871.         'STORE_NAME': -1,
  872.         'STORE_ATTR': -2,
  873.         'DELETE_ATTR': -1,
  874.         'STORE_GLOBAL': -1,
  875.         'BUILD_MAP': 1,
  876.         'COMPARE_OP': -1,
  877.         'STORE_FAST': -1,
  878.         'IMPORT_STAR': -1,
  879.         'IMPORT_NAME': -1,
  880.         'IMPORT_FROM': 1,
  881.         'LOAD_ATTR': 0,
  882.         'SETUP_EXCEPT': 3,
  883.         'SETUP_FINALLY': 3,
  884.         'FOR_ITER': 1,
  885.         'WITH_CLEANUP': -1 }
  886.     patterns = [
  887.         ('BINARY_', -1),
  888.         ('LOAD_', 1)]
  889.     
  890.     def UNPACK_SEQUENCE(self, count):
  891.         return count - 1
  892.  
  893.     
  894.     def BUILD_TUPLE(self, count):
  895.         return -count + 1
  896.  
  897.     
  898.     def BUILD_LIST(self, count):
  899.         return -count + 1
  900.  
  901.     
  902.     def CALL_FUNCTION(self, argc):
  903.         (hi, lo) = divmod(argc, 256)
  904.         return -(lo + hi * 2)
  905.  
  906.     
  907.     def CALL_FUNCTION_VAR(self, argc):
  908.         return self.CALL_FUNCTION(argc) - 1
  909.  
  910.     
  911.     def CALL_FUNCTION_KW(self, argc):
  912.         return self.CALL_FUNCTION(argc) - 1
  913.  
  914.     
  915.     def CALL_FUNCTION_VAR_KW(self, argc):
  916.         return self.CALL_FUNCTION(argc) - 2
  917.  
  918.     
  919.     def MAKE_FUNCTION(self, argc):
  920.         return -argc
  921.  
  922.     
  923.     def MAKE_CLOSURE(self, argc):
  924.         return -argc
  925.  
  926.     
  927.     def BUILD_SLICE(self, argc):
  928.         if argc == 2:
  929.             return -1
  930.         elif argc == 3:
  931.             return -2
  932.         
  933.  
  934.     
  935.     def DUP_TOPX(self, argc):
  936.         return argc
  937.  
  938.  
  939. findDepth = StackDepthTracker().findDepth
  940.